package com.sz.biz.logistics.base.service.impl;

import com.sz.biz.common.AbstractVersionEntityService;
import com.sz.biz.common.base.dto.CommonAreaList;
import com.sz.biz.common.base.dto.CountryArea;
import com.sz.biz.common.base.service.AreaService;
import com.sz.biz.common.constants.ErrorCodes;
import com.sz.biz.common.constants.ModuleNames;
import com.sz.biz.logistics.base.dto.CountryPort;
import com.sz.biz.logistics.base.dto.Postcode;
import com.sz.biz.logistics.base.dto.RegionDto;
import com.sz.biz.logistics.base.dto.RegionSchemaDto;
import com.sz.biz.logistics.base.entity.*;
import com.sz.biz.logistics.base.service.*;
import com.sz.biz.logistics.constants.ProductGroupCode;
import com.sz.biz.logistics.constants.RegionConstants;
import com.sz.biz.logistics.core.service.QuotationService;
import com.sz.common.base.constants.UserActions;
import com.sz.common.base.dao.ParamData;
import com.sz.common.base.dto.QResultDto;
import com.sz.common.base.dto.QueryParams;
import com.sz.common.base.exception.Exceptions;
import com.sz.common.base.utils.CollectionUtils;
import com.sz.common.base.utils.EntityUtils;
import com.sz.common.core.service.PrincipalLogUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.util.*;

/**
 * Package: com.sz.biz.logistics.base.service.impl <br>
 * Function: 分区service实现类 <br>
 * Author: hpeng.wang. <br>
 * Date: 2017-02-15 15:01:00.
 */
@Service("RegionService")
public class RegionServiceImpl extends AbstractVersionEntityService implements RegionService {
    @Autowired
    private RegionItemService itemService;
    @Autowired
    private AreaService areaService;
    @Autowired
    RegionSchemaService schemaService;
    @Autowired
    QuotationService quotationService;
    @Autowired
    AirportService airportService;
    @Autowired
    PortService portService;

    @Override
    protected String getMapperNamespace() {
        return "com.sz.biz.logistics.base.entity.mapper.RegionMapper";
    }

    @Override
    public int save(RegionDto dto) throws ParseException {

        //没有任何地区或邮编信息，视为无效信息
        if (CollectionUtils.isEmpty(dto.getAreas()) && CollectionUtils.isEmpty(dto.getPostcodes()) && CollectionUtils.isEmpty(dto.getPorts())) {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "要保存的地区或邮编未填写！");
        }
        boolean isRef = quotationService.isRegionSchemaReferenced(dto.getSchemaId(), true);
        if (isRef) {
            throw Exceptions.bizException(ErrorCodes.ERROR_BIZ_REGION_SCHEMA_REF, dto.getSchemaId());
        }
        this.checkCountryArea(dto.getSchemaId(), dto.getAreas(), dto.getPostcodes(), dto.getPorts());
        //3、保存分区数据
        Region region = new Region();
        EntityUtils.copyPropertiesIgnoreNull(dto, region);
        region.setId(null);
        super.save(region);

        //4、保存分区item数据
        RegionSchema regionSchema = schemaService.findEntryActivedByUid(dto.getSchemaId());
        if (ObjectUtils.isEmpty(regionSchema)) {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "分区方案未找到，不能保存分区！");
        }
        List<RegionItem> itemList = this.assembleItems(dto.getAreas(), dto.getPostcodes(), dto.getPorts(), regionSchema.getAddressType(), region.getId());
        itemService.batchSave(itemList);

        //4.1、冗余一个所有分区明细的字段，方便查询
        RegionSchemaDto regionSchemaDto = schemaService.findActivedByUid(region.getSchemaId());
        List<Integer> regionIds = EntityUtils.getIntPropListFromBeans(regionSchemaDto.getRegionlist(), "id");
        List<RegionItem> regionItemList = itemService.findByRegionIds(regionIds);
        StringBuffer sb = new StringBuffer();
        for (RegionItem regionItem : regionItemList) {
            sb.append(regionItem.getDetailString()).append("|");
        }
        schemaService.updateItemDetail(regionSchemaDto.getId(), sb.toString());

        //5、保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("ADD_REGION", region);
        dataBackup.put("ADD_REGION_ITEM", itemList);
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_REGION, UserActions.ADD, "添加分区", dataBackup);

        //6、返回
        return region.getId();
    }


    @Override
    public void delete(Integer id) {
        if (id != null && id > 0) {
            this.batchDelete(Arrays.asList(id));
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void batchDelete(List<Integer> ids) {
        if (!CollectionUtils.isEmpty(ids)) {
            List<Region> regionList = findByIds(ids);//根据ids查询对应的分区数据集合
            if (!CollectionUtils.isEmpty(regionList)) {
                //备份数据
                Map<String, Object> dataBackup = new HashMap<>();
                dataBackup.put("BATCH_DELETE_REGION", regionList);
                PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_REGION, UserActions.DELETE, "删除分区", dataBackup);
                List<String> uids = new ArrayList<>();
                regionList.forEach(region -> {
                    //判断分区方案是否有引用
                    boolean isRef = quotationService.isRegionSchemaReferenced(region.getSchemaId(), false);
                    if (isRef) {
                        throw Exceptions.bizException(ErrorCodes.ERROR_BIZ_REGION_SCHEMA_REF, region.getSchemaId());
                    }
                    uids.add(region.getUid());
                });
                super.deleteEntities(uids);

                for (Region region : regionList) {
                    //对冗余字段进行处理
                    RegionSchemaDto regionSchemaDto = schemaService.findActivedByUid(region.getSchemaId());
                    List<Integer> regionIds = EntityUtils.getIntPropListFromBeans(regionSchemaDto.getRegionlist(), "id");
                    List<RegionItem> regionItemList = itemService.findByRegionIds(regionIds);
                    StringBuffer sb = new StringBuffer();
                    for (RegionItem regionItem : regionItemList) {
                        sb.append(regionItem.getDetailString()).append("|");
                    }
                    schemaService.updateItemDetail(regionSchemaDto.getId(), sb.toString());
                }

            }
        }

    }

    @Override
    public void deleteBySchemaIds(List<String> schemaUids) {
        if (!CollectionUtils.isEmpty(schemaUids)) {
            //判断分区方案是否有引用
            schemaUids.forEach(schemaUid -> {
                boolean isRef = quotationService.isRegionSchemaReferenced(schemaUid, false);
                if (isRef) {
                    throw Exceptions.bizException(ErrorCodes.ERROR_BIZ_REGION_SCHEMA_REF, schemaUid);
                }
            });

            List<Integer> regionId = findIdBySchemaUids(schemaUids, true);//为null代表查询所有的数据
            batchDelete(regionId);
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public int update(Integer id, RegionDto dto) {
        Region region = findById(id);
        if (!ObjectUtils.isEmpty(region)) {
            //判断分区方案是否有引用
            boolean isRef = quotationService.isRegionSchemaReferenced(region.getSchemaId(), true);
            if (isRef) {
                throw Exceptions.bizException(ErrorCodes.ERROR_BIZ_REGION_SCHEMA_REF, region.getSchemaId());
            }

            //添加要更新数据的日志信息
            Map<String, Object> dataBackup = new HashMap<>();
            dataBackup.put("UPDATE_REGION", region);
            PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_REGION, UserActions.UPDATE, "修改分区", dataBackup);
            EntityUtils.copyPropertiesIgnoreNull(dto, region);
            super.updateVersionEntity(region);
            //这里用region的schemaId的原因是因为dto中可能并不给传schemaId
            this.checkCountryArea(region.getSchemaId(), dto.getAreas(), dto.getPostcodes(), dto.getPorts());

            //4、保存分区item数据
            RegionSchema regionSchema = schemaService.findEntryActivedByUid(dto.getSchemaId());
            if (ObjectUtils.isEmpty(regionSchema)) {
                throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "分区方案未找到！！");
            }
            List<RegionItem> itemList = this.assembleItems(dto.getAreas(), dto.getPostcodes(), dto.getPorts(), regionSchema.getAddressType(), region.getId());
            itemService.batchSave(itemList);
            //4.1、冗余一个所有分区明细的字段，方便查询
            RegionSchemaDto regionSchemaDto = schemaService.findActivedByUid(region.getSchemaId());
            List<Integer> regionIds = EntityUtils.getIntPropListFromBeans(regionSchemaDto.getRegionlist(), "id");
            List<RegionItem> regionItemList = itemService.findByRegionIds(regionIds);
            StringBuffer sb = new StringBuffer();
            for (RegionItem regionItem : regionItemList) {
                sb.append(regionItem.getDetailString()).append("|");
            }
            schemaService.updateItemDetail(regionSchemaDto.getId(), sb.toString());
        }
        return region.getId();
    }

    @Override
    public Region findById(Integer id) {
        Region region = null;
        if (id != null && id > 0) {
            List<Region> regionList = this.findByIds(Arrays.asList(id));
            if (!regionList.isEmpty()) {
                region = regionList.get(0);
            }
        }
        return region;
    }

    @Override
    public List<Region> findByIds(List<Integer> ids) {
        List<Region> regionList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(ids)) {
            ParamData pd = new ParamData();
            pd.put("ids", ids);
            regionList = dao.findForList(getSqlName("findByIds"), pd, Region.class);
        }
        return regionList;
    }

    @Override
    public RegionDto findDtoById(Integer id) {
        RegionDto regionDto = null;
        if (id != null && id > 0) {
            List<RegionDto> regionDtoList = this.findDtoByIds(Arrays.asList(id));
            if (!CollectionUtils.isEmpty(regionDtoList)) {
                regionDto = regionDtoList.get(0);
            }
        }
        return regionDto;
    }

    @Override
    public List<RegionDto> findDtoBySchemaUid(String schemaUid) {
        List<RegionDto> regionDtoList = new ArrayList<>();
        if (StringUtils.hasLength(schemaUid)) {
            List<Integer> regionIds = findIdBySchemaUid(schemaUid);
            regionDtoList = this.findDtoByIds(regionIds);
        }
        return regionDtoList;
    }

    @Override
    public List<RegionItem> findItemBySchemaUid(String schemaUid) {
        List<Integer> ids = this.findIdBySchemaUid(schemaUid);
       List<RegionItem> itemList =  itemService.findByRegionIds(ids);
        return itemList;
    }

    @Override
    public List<Integer> findIdBySchemaUid(String schemaUid) {
        List<Integer> idList = new ArrayList<>();
        if (StringUtils.hasLength(schemaUid)) {
            idList = this.findIdBySchemaUids(Arrays.asList(schemaUid), true);
        }
        return idList;
    }

    @Override
    public List<Region> findRegionBySchemaUids(List<String> schemaUids, Boolean isActive, Date time) {
        List<Region> regionList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(schemaUids)) {
            ParamData pd = new ParamData();
            pd.put("schemaIds", schemaUids);
            pd.put("isActive", isActive);
            pd.put("time", time);
            regionList = dao.findForList(getSqlName("findRegionBySchemaUids"), pd, Region.class);
        }
        return regionList;
    }

    @Override
    public QResultDto findByParam(QueryParams params) {
        ParamData pd = this.convertQueryParams(params);


        List<Integer> regionIds;
        String schemaId = (String) pd.get("schemaId");
        int addressType = 0;
        RegionSchema regionSchema = schemaService.findEntryActivedByUid(schemaId);
        if (!ObjectUtils.isEmpty(regionSchema)) {
            addressType = regionSchema.getAddressType();
        }

        if (addressType == ProductGroupCode.SEA_TRANSPORT ) {//海运
            regionIds = dao.findForList(getSqlName("findPortByParamListPage"), pd, Integer.class);
        } else if (addressType == ProductGroupCode.AIR_TRANSPORT ) {//空运
            regionIds = dao.findForList(getSqlName("findAirPortByParamListPage"), pd, Integer.class);

        } else {
            regionIds = dao.findForList(getSqlName("findByParamListPage"), pd, Integer.class);

        }

        CollectionUtils.removeDuplication(regionIds);

        List<RegionDto> regionDtoList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(regionIds)) {
            regionDtoList = this.findDtoByIds(regionIds);
        }
        return new QResultDto(regionDtoList, pd.getPagination());
    }

    @Override
    public List<Region> findByParam(String schemaId, String query) {
        return this.findByParam(schemaId, query, true);
    }

    @Override
    public List<Region> findRegion(List<String> uids, Boolean isActive, Date time) {
        List<Region> regionList = null;
        if (!CollectionUtils.isEmpty(uids)) {
            ParamData pd = new ParamData();
            pd.put("uids", uids);
            pd.put("isActive", isActive);
            pd.put("time", time);
            regionList = dao.findForList(getSqlName("findRegion"), pd, Region.class);
            for (Region region : regionList) {
                region.setRegionItemList(itemService.findByRegionId(region.getId()));
            }
        }
        return regionList;
    }

    @Override
    public Region findActivedByUid(String uid) {
        Region region = null;
        List<Region> regionList = this.findRegion(Arrays.asList(uid), true, null);
        if (!CollectionUtils.isEmpty(regionList)) {
            region = regionList.get(0);
        }
        return region;
    }

    @Override
    public Region findByUidAndTime(String uid, Date time) {
        Region region = null;
        List<Region> regionList = this.findRegion(Arrays.asList(uid), null, time);
        if (!CollectionUtils.isEmpty(regionList)) {
            region = regionList.get(0);
        }
        return region;
    }

    @Override
    public void checkCode(int id, String schemaUid, String code) {
        ParamData pd = new ParamData();
        pd.put("schemaId", schemaUid);
        pd.put("code", code);
        pd.put("id", id);
        int count = (Integer) dao.findForObject(getSqlName("findCountByCode"), pd);
        if (count > 0) {
            throw Exceptions.bizException(ErrorCodes.ERROR_MODEL_CODE_EXIST, "");
        }
    }

    private List<RegionDto> findDtoByIds(List<Integer> regionIds) {
        //1、查询出分区的信息
        List<Region> regions = this.findByIds(regionIds);
        List<Region> list = new ArrayList<>();
      Map<Integer,Region>  map =  EntityUtils.getIntKeyMapFromBeans(regions,"id");

        for (Integer regionId : regionIds) {
           if(!ObjectUtils.isEmpty( map.get(regionId))){
               list.add( map.get(regionId));
            }
        }
        regions = list;
        if (!CollectionUtils.isEmpty(regions)) {//当查询出来的信息存在时
            List<RegionDto> regionDtos = new ArrayList<>();

            Map<Integer, List<RegionItem>> regionItemMap = new HashMap<>();
            List<RegionItem> regionItemList = itemService.findByRegionIds(regionIds);//根据biz_region的id集合从表biz_region_item中查询出指定id的所有的item
            for (RegionItem regionItem : regionItemList) {
                if (regionItemMap.get(regionItem.getRegionId()) == null) {
                    List<RegionItem> regionItems = new ArrayList<>();
                    regionItemMap.put(regionItem.getRegionId(), regionItems);
                }
                regionItemMap.get(regionItem.getRegionId()).add(regionItem);
            }


            for (Region region : regions) {
                RegionDto dto = new RegionDto(region);//将region信息复制到regionDto中
                List<RegionItem> regionItems = regionItemMap.get(region.getId());

                //对postcode进行填充
                if (!CollectionUtils.isEmpty(regionItems)) {

                    //获取要处理的机场或港口的map数据
                    Map<Integer, Port> portMap = new HashMap<>();
                    Map<Integer, Airport> airportMap = new HashMap<>();
                    this.processPortMap(regionItems, portMap, airportMap);

                    //处理regionitem的数据
                    regionItems.forEach(regionItem -> {
                        String strItemDetail = regionItem.getItemDetail();
                        if (StringUtils.isEmpty(strItemDetail)) {
                            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "分区详情：" + regionItem.getId() + "的detail异常");
                        }
                        String[] itemDetail = strItemDetail.split("_");
                        if (itemDetail != null && itemDetail.length == 2) {
                            if (regionItem.getType() == CountryAreaType.COUNTRY.value() || regionItem.getType() == CountryAreaType.CHINAAREA.value() || regionItem.getType() == CountryAreaType.ABROADAREA.value()) {//填充国家
                                dto.putArea(new CountryArea(itemDetail[0], itemDetail[1]));
                            } else if (regionItem.getType() == 4) {//填充邮编
                                String[] strName = itemDetail[1].split("/");
                                dto.putPostcode(new Postcode(regionItem.getStartPostcode(), regionItem.getEndPostcode(), regionItem.getCountry(), strName[0]));
                            } else if (regionItem.getType() == CountryAreaType.PORTADDRESS.value()) {//填充港口，港口要显示其名称、英文名称
                                String name = "", enName = "";
                                Port port = portMap.get(regionItem.getTransportId());//获取机场entity数据
                                if (!ObjectUtils.isEmpty(port)) {
                                    name = port.getName();
                                    enName = port.getEnglishName();
                                }
                                dto.putPorts(new CountryPort(regionItem.getCountry(), regionItem.getAreaId(), regionItem.getTransportId(), name, enName));
                            } else if (regionItem.getType() == CountryAreaType.AIRADDRESS.value()) {//机场，机场要显示名称、三字码
                                String name = "", triadCode = "";
                                Airport port = airportMap.get(regionItem.getTransportId());//获取港口entity数据
                                if (!ObjectUtils.isEmpty(port)) {
                                    name = port.getName();
                                    triadCode = port.getTriadCode();//机场三字码
                                }
                                dto.putPorts(new CountryPort(regionItem.getCountry(), regionItem.getAreaId(), regionItem.getTransportId(), name, null, triadCode, regionItem.getType()));
                            }
                        } else {
                            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "分区详情：" + regionItem.getId() + "的detail异常");
                        }
                    });
                }
                regionDtos.add(dto);//放到regionDtos集合中
            }
            return regionDtos;
        }
        return null;
    }

    private void processPortMap(List<RegionItem> regionItems, Map<Integer, Port> portMap, Map<Integer, Airport> airportMap) {
        List<Integer> portIds = new ArrayList<>();
        List<Integer> airPortIds = new ArrayList<>();
        regionItems.forEach(regionItem -> {
            if (regionItem.getType() == CountryAreaType.PORTADDRESS.value()) {//港口
                portIds.add(regionItem.getTransportId());
            } else if (regionItem.getType() == CountryAreaType.AIRADDRESS.value()) {//机场
                airPortIds.add(regionItem.getTransportId());
            }

        });
        if (!CollectionUtils.isEmpty(portIds) && !CollectionUtils.isEmpty(airPortIds)) {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "分区详情类型异常");
        }
        //获取港口数据

        if (!CollectionUtils.isEmpty(portIds)) {
            List<Port> portList = portService.findShortById(portIds);
            portList.forEach(port -> portMap.put(port.getId(), port));
        }
        //获取机场数据

        if (!CollectionUtils.isEmpty(airPortIds)) {
            List<Airport> airportList = airportService.findShortById(airPortIds);
            airportList.forEach(airport -> airportMap.put(airport.getId(), airport));
        }
    }

    @Override
    public List<Integer> findIdBySchemaUids(List<String> schemaUids, Boolean isActive) {
        List<Integer> idList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(schemaUids)) {
            ParamData pd = new ParamData();
            pd.put("schemaIds", schemaUids);
            pd.put("isActive", isActive);
            idList = dao.findForList(getSqlName("findIdBySchemaIds"), pd, Integer.class);
        }
        return idList;
    }

    private List<Region> findByParam(String schemaId, String query, Boolean isActive) {
        List<Region> regionList = new ArrayList<>();
        if (StringUtils.hasLength(schemaId)) {
            ParamData pd = new ParamData();
            pd.put("schemaId", schemaId);
            pd.put("query", query);
            pd.put("isActive", isActive);
            regionList = dao.findForList(getSqlName("findByParam"), pd, Region.class);
            for (Region region : regionList) {
                region.setRegionItemList(itemService.findByRegionId(region.getId()));
            }
        }
        return regionList;
    }

    /**
     * 组装要保存的分区item集合
     *
     * @param countryAreaList 里面包含要保存的分区详情国家数据
     * @param postcodeList    邮编的集合
     * @param countryPortList 运输工具id的集合
     * @param addressType     地址的类型 1、全球海运 6、全球空运 11、全球速递
     * @param id              分区的外键id  @return　组装好的分区itemlist集合
     */
    private List<RegionItem> assembleItems(List<CountryArea> countryAreaList, List<Postcode> postcodeList, List<CountryPort> countryPortList, int addressType, Integer id) {
        List<RegionItem> regionItemList = new ArrayList<>();

        if (!CollectionUtils.isEmpty(countryPortList)) {
            List<Integer> portIds = new ArrayList<>();
            List<Integer> airPortIds = new ArrayList<>();
            List<RegionItem> regionItems = new ArrayList<>();
            for (CountryPort countryPort : countryPortList) {
                if (addressType != 1 && addressType != 6) {//1代表海运，在分区详情里5代表海运 6代表空运，在分区详情里6代表空运
                    throw Exceptions.bizExceptionData(ErrorCodes.ERROR_BIZ_REGION_ADDRESS_TYPE, addressType);
                }
                RegionItem regionItem = new RegionItem();
                regionItem.setRegionId(id);
                regionItem.setCountry(countryPort.getCountryCode());
                regionItem.setAreaId(countryPort.getAreaId());
                regionItem.setTransportId(countryPort.getTransportId());
                if (addressType == 1) {//代表海运
                    portIds.add(countryPort.getTransportId());
                    regionItem.setType(CountryAreaType.PORTADDRESS.value());
                } else {//6代表空运
                    regionItem.setType(CountryAreaType.AIRADDRESS.value());
                    airPortIds.add(countryPort.getTransportId());
                }
                regionItemList.add(regionItem);

                //拼装查询地址要用的信息
                RegionItem ri = new RegionItem();
                ri.setCountry(countryPort.getCountryCode());
                ri.setAreaId(countryPort.getAreaId());
                if ("CN".equalsIgnoreCase(countryPort.getCountryCode())) {
                    ri.setType(2);//中国地区
                } else {
                    ri.setType(3);//国外地址
                }
                regionItems.add(ri);
            }
            //填充itemDetail字段的数据
            this.processPortNames(regionItemList, portIds, airPortIds, regionItems);
            return regionItemList;
        }


        for (CountryArea countryArea : countryAreaList) {//保存地区的分区方案详情
            String countryCode = countryArea.getCountryCode();

            RegionItem regionItem = new RegionItem();
            if (!countryCode.contains("/")) {//国家
                regionItem.setType(CountryAreaType.COUNTRY.value());
                regionItem.setCountry(countryCode);
            } else if (countryCode.toUpperCase().contains("CN") && countryCode.contains("/")) {//中国地区
                regionItem.setType(CountryAreaType.CHINAAREA.value());
                regionItem.setCountry(countryCode.split("/")[0]);//第一位存的国家
                regionItem.setAreaId(countryCode.split("/")[countryCode.split("/").length - 1]);//最后一位存要保存的地区id

            } else {//国外地区
                regionItem.setType(CountryAreaType.ABROADAREA.value());
                regionItem.setCountry(countryCode.split("/")[0]);//第一位存的国家
                regionItem.setAreaId(countryCode.split("/")[countryCode.split("/").length - 1]);//最后一位存要保存的地区id
            }

            regionItem.setRegionId(id);
            regionItemList.add(regionItem);
        }
        for (Postcode postcode : postcodeList) {//保存邮编分区item
            RegionItem entry = new RegionItem();
            entry.setRegionId(id);
            entry.setCountry(postcode.getCountry());
            entry.setType(CountryAreaType.POSTCODE.value());
            entry.setStartPostcode(postcode.getStartPostcode());
            entry.setEndPostcode(postcode.getEndPostcode());
            regionItemList.add(entry);
        }

        //对Area进行填充
        CommonAreaList list = new CommonAreaList(regionItemList);
        areaService.fillAllPathCommonAreaNames(list);

        Map<String, CountryArea> countryAreaMap = new HashMap<>();
        list.forEach(countryArea -> {
            String[] countryAreaStr = countryArea.getCountryCode().split("/");
            String country = countryAreaStr[0];
            String key = countryArea.getType() + "_" + country + "_" + countryArea.getAreaId();
            countryAreaMap.put(key, countryArea);
        });
        for (RegionItem regionitem : regionItemList) {
            String itemDetail;
            if (regionitem.getType() == 4) {
                itemDetail = regionitem.getCountry() + "/" + regionitem.getStartPostcode() + "/" + regionitem.getEndPostcode() + "_" + areaService.getCountryNameByCode(regionitem.getCountry()) + "/" + regionitem.getStartPostcode() + "/" + regionitem.getEndPostcode();
            } else {
                String key = regionitem.getType() + "_" + regionitem.getCountry() + "_" + regionitem.getAreaId();
                CountryArea countryArea = countryAreaMap.get(key);
                itemDetail = countryArea.getCountryCode() + "_" + countryArea.getName();
            }

            regionitem.setItemDetail(itemDetail);
        }


        return regionItemList;
    }

    private void processPortNames(List<RegionItem> regionItemList, List<Integer> portIds, List<Integer> airPortIds, List<RegionItem> regionItems) {
        CommonAreaList list;//对Area进行填充,并取得map形式的数据
        list = new CommonAreaList(regionItems);
        areaService.fillAllPathCommonAreaNames(list);
        Map<String, CountryArea> countryAreaMap = new HashMap<>();
        list.forEach(countryArea -> {
            String[] countryAreaStr = countryArea.getCountryCode().split("/");
            String country = countryAreaStr[0];
            String key = country + "_" + countryArea.getAreaId();
            countryAreaMap.put(key, countryArea);
        });


        //获取港口数据
        Map<Integer, Port> portMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(portIds)) {
            List<Port> portList = portService.findShortById(portIds);
            portList.forEach(port -> portMap.put(port.getId(), port));
        }

        //获取机场数据
        Map<Integer, Airport> airportMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(airPortIds)) {
            List<Airport> airportList = airportService.findShortById(airPortIds);
            airportList.forEach(airport -> airportMap.put(airport.getId(), airport));
        }


        for (RegionItem regionItem : regionItemList) {
            String key = regionItem.getCountry() + "_" + regionItem.getAreaId();//CN_100010(国家_地区)
            CountryArea countryArea = countryAreaMap.get(key);
            String countryCode = countryArea.getCountryCode() + "/" + regionItem.getTransportId();//在字符串后面加上运输工具
            String name = countryArea.getName() + "/";//在字符串后面加上运输工具的名字
            if (regionItem.getType() == CountryAreaType.PORTADDRESS.value()) {//港口
                name = name + portMap.get(regionItem.getTransportId()).getName();
            } else if (regionItem.getType() == CountryAreaType.AIRADDRESS.value()) {//机场
                name = name + airportMap.get(regionItem.getTransportId()).getName();
            }
            regionItem.setItemDetail(countryCode + "_" + name);
        }
    }

    private void checkCountryArea(String schemaId, List<CountryArea> areas, List<Postcode> postcodes, List<CountryPort> ports) {
        //1、查询现有分区明细表中所有数据
        List<RegionItem> regionItemList = itemService.findRegionItemByRegionIdsAndIsActive(schemaId, true);


        //2、判断地区、邮编的合法性

        //对数据库已存方案明细，提取全路径（国内与国外地区都有）的list集合
        CommonAreaList list = new CommonAreaList(regionItemList);
        areaService.fillAllPathCommonAreaNames(list);
        List<CountryArea> dataCountryAreaList = list;

        List<Postcode> dataPostcodeList = new ArrayList<>();
        List<CountryPort> dataPortList = new ArrayList<>();
        regionItemList.forEach(regionItem -> {
            if (regionItem.getType() == RegionConstants.Type.ZIP_CODE ) {
                dataPostcodeList.add(new Postcode(regionItem.getStartPostcode(), regionItem.getEndPostcode(), regionItem.getCountry()));
            } else if (regionItem.getType() == RegionConstants.Type.SEA_ADDRESS  ||
                    regionItem.getType() == RegionConstants.Type.AIR_ADDRESS) {
                dataPortList.add(new CountryPort(regionItem.getCountry(), regionItem.getTransportId(), regionItem.getType()));
            }
        });

        if (!CollectionUtils.isEmpty(dataCountryAreaList)) {
            areaService.judgeArea(areas, dataCountryAreaList);//判断编码的合法性
            areaService.judgePostcode(postcodes, dataPostcodeList);
        }

        //3、校验如果要保存的是运输工具，那么这里要做校验
        this.judgePort(ports, dataPortList);
    }

    private void judgePort(List<CountryPort> dtoPorts, List<CountryPort> dataPortList) {
        Set<CountryPort> countryPorts = this.validPort(dtoPorts);//1、校验前端传递过来的邮编的有效性,因为要给前端返回一个集合，所以这里用集合统一处理
        //判断数据库中已经保存的数据与前端传递过来的数据重复性
        if (!CollectionUtils.isEmpty(dataPortList)) {
            for (CountryPort dtoCountryPort : dtoPorts) { //前端传过来的postcode与后端数据库重复判断
                int count = Collections.frequency(dataPortList, dtoCountryPort);
                if (count >= 1) {//如果数据库中有一个代表已经重复，所以这里用等于1
                    countryPorts.add(dtoCountryPort);
                }
            }
        }
        if (!CollectionUtils.isEmpty(countryPorts)) {
            throw Exceptions.bizExceptionData(ErrorCodes.ERROR_COMMON, countryPorts, "要保存的运输工具有重复！");
        }
    }

    /**
     * 校验前端传过来的邮编集合是否有重复
     *
     * @param countryPortList 邮编集合
     * @return 重复的邮编数据
     */
    private Set<CountryPort> validPort(List<CountryPort> countryPortList) {
        Set<CountryPort> countryPortSet = new HashSet<>();
        if (!CollectionUtils.isEmpty(countryPortList)) {
            for (CountryPort countryPort : countryPortList) {
                if (StringUtils.isEmpty(countryPort.getAreaId())) {
                    throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "地区不能为空！");
                }
                if (!StringUtils.hasLength(countryPort.getCountryCode()) || countryPort.getTransportId() == null || countryPort.getTransportId() <= 0) {
                    throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "要保存的运输工具包含空！");
                }
                int count = Collections.frequency(countryPortList, countryPort);
                if (count > 1) {
                    countryPortSet.add(countryPort);
                }
            }
        }
        return countryPortSet;
    }
}
